import gc
import os
import shutil
import subprocess
import platform
from colorama import  Fore
from core.ModifyConfig import _run_config_scripts
from utils.config import PROJECT_DIR, ohpm_path, node_path, hvigor_path
from core.ReadExcel import get_repo_info

def clone_and_build(library_name):
    """克隆仓库并构建项目，返回测试结果"""
    # 运行库之前杀掉node进程
    kill_previous_process()
    try:
        # 准备工作
        os.environ["GIT_CLONE_PROTECTION_ACTIVE"] = "false"
        
        # 从ReadExcel获取仓库信息
        owner, name, sub_dir = get_repo_info(library_name)
        print(f"获取到仓库信息: owner={owner}, name={name}, sub_dir={sub_dir}")
        
        # 1. 创建并进入Libraries目录
        libraries_dir = os.path.abspath(os.path.join(os.getcwd(), "Libraries"))
        os.makedirs(libraries_dir, exist_ok=True)
        os.chdir(libraries_dir)
        
        # 2. 克隆或更新仓库
        _clone_repo(library_name)
        
        # 3. 进入项目目录
        # 特殊处理aki库，需要进入到特定的单元测试目录
        if name == "aki":
            target_dir = os.path.join(name, "platform", "ohos", "publish")
            print(Fore.YELLOW + f"检测到aki库，将进入特定目录: {target_dir}" + Fore.RESET)
        else:
            target_dir = name if not sub_dir else os.path.join(name, sub_dir)
            
        if not os.path.exists(target_dir):
            raise FileNotFoundError(f"目标目录 {target_dir} 不存在")
            
        os.chdir(target_dir)
        print(f"当前工作目录: {os.getcwd()}")
        # 4.执行配置脚本
        _run_config_scripts()

        # 5.安装ohpm依赖
        _install_ohpm_dependencies()

        # 6.grpc的前置步骤
        if name == "ohos_grpc_node":
            # 替换protobufjs类型定义文件
            src_file = os.path.join("protobufjs", "index.d.ts")
            dest_file = os.path.join("library", "oh_modules", "@ohos", "protobufjs", "src", "main", "ets", "index.d.ts")
            
            if os.path.exists(src_file) and os.path.exists(dest_file):
                try:
                    shutil.copy2(src_file, dest_file)
                    print(f"成功替换protobufjs类型定义文件: {dest_file}")
                except Exception as e:
                    print(f"替换protobufjs类型定义文件失败: {str(e)}")
            else:
                print(f"警告：找不到源文件或目标文件: 源={src_file}, 目标={dest_file}")

        # 7.检查并复制必要文件
        _copy_necessary_files()

        # 8.构建项目
        _build_project()

    except subprocess.CalledProcessError as e:
        print(f"执行命令失败: {e}")
    finally:
        os.chdir(PROJECT_DIR)
        # 手动触发垃圾回收
        gc.collect()
        print("已成功进行垃圾回收")

def kill_previous_process(platfrom=None):
    # 新增：如果 platfrom 为 None，则使用 platform 模块作为默认值
    if platfrom is None:
        platfrom = platform
    
    try:
        if platfrom.system() == "Windows":
            subprocess.run(["taskkill", "/f", "/im", "node.exe"], check=True)
        else:
            subprocess.run(["pkill", "-f", "node"], check=True)
            print("已成功终止node进程")
    except subprocess.CalledProcessError as e:
        print(f"终止进程时出错，可能进程不存在或没有权限: {e}")

def _install_ohpm_dependencies():
    """安装ohpm依赖"""
    ohpm_registries = "https://ohpm.openharmony.cn/ohpm/"
    subprocess.run([ohpm_path, "install", "--all", "--registry", ohpm_registries, "--strict_ssl", "false"],
                   check=True)

def _copy_necessary_files(library_name=None):
    """复制必要的文件到项目目录"""
    print("开始检查并复制必要文件...")
    original_dir = os.getcwd()
    try:
        # 使用传入的库名或获取当前目录名
        current_library = library_name if library_name else os.path.basename(os.getcwd())

        # 将当前库名转为小写，用于不区分大小写的匹配
        if isinstance(current_library, dict) and 'name' in current_library:
            current_library_str = current_library['name']
        elif isinstance(current_library, str):
            current_library_str = current_library
        else:
            print(f"警告：无法识别的库名格式: {current_library}，使用当前目录名")
            current_library_str = os.path.basename(os.getcwd())
        print(f"正在处理库: {current_library_str}")

        # 获取当前工作目录
        if current_library_str == "publish":
            os.chdir("../../..")
        current_dir = os.getcwd()

        # 定义库名和对应的目标目录映射
        library_target_paths = {
            "ohos_mqtt": os.path.join(current_dir, 'ohos_Mqtt'),
            "ohos_coap": os.path.join(current_dir, 'libcoap'),
            "ohos_ijkplayer": os.path.join(current_dir, 'ijkplayer'),
            "ohos_luaarkts": os.path.join(current_dir, 'luaarkts'),
            "ohos_video_trimmer": os.path.join(current_dir, 'videotrimmer'),
            "ohos_videocompressor": os.path.join(current_dir, 'videoCompressor'),
            "publish": os.path.join(current_dir, 'platform', 'ohos', 'publish', 'aki'),
            "ohos_jsonwebtoken": os.path.join(current_dir, 'jsonwebtoken'),
            "ohos-SwipeLayout": os.path.join(current_dir, 'SwipeLayout'),
			"linphone_napi": os.path.join(current_dir, 'ohos_linphone')
        }

        # 库名的显示名称映射
        library_display_names = {
            "ohos_mqtt": "ohos_Mqtt",
            "ohos_coap": "libcoap",
            "ohos_ijkplayer": "ijkplayer",
            "ohos_videocompressor": "videoCompressor",
            "ohos_luaarkts": "luaarkts",
            "publish": "aki",
            "ohos_video_trimmer": "videotrimmer",
            "ohos_jsonwebtoken": "jsonwebtoken",
            "ohos-SwipeLayout": "SwipeLayout",
			"linphone_napi": "ohos_linphone"
        }

        # 检查是否存在 library 目录或 library_display_names 中定义的特殊情况
        if not os.path.exists(os.path.join(current_dir, 'library')) and current_library_str not in library_display_names:
            print(f"当前库 '{current_library_str}' 既没有 library 目录，也没有特殊情况，跳过复制必要文件")
            return

        # 检查当前库是否在需要处理的库列表中
        target_dir = None
        for lib_key in library_target_paths:
            if current_library_str == lib_key or current_library_str.endswith(f'_{lib_key}'):
                print(f"匹配到预定义库: {library_display_names.get(lib_key, lib_key)}")
                target_dir = library_target_paths[lib_key]
                break

        # 如果不是预定义的库，使用默认的library目录
        if target_dir is None:
            print(f"当前库 '{current_library_str}' 不在预定义列表中，使用默认目录")
            target_dir = os.path.join(current_dir, 'library')

        # 复制必要文件
        required_files = ["README.md", "LICENSE", "CHANGELOG.md"]
        for file in required_files:
            if file == "LICENSE" and os.path.isfile("LICENSE.txt"):
                # 如果找到LICENSE.txt，改名为LICENSE后复制
                target_file = os.path.join(target_dir, "LICENSE")
                shutil.copy2("LICENSE.txt", target_file)
                print(f"已复制文件: LICENSE.txt -> {target_file}")
            elif not os.path.isfile(file):
                raise FileNotFoundError(f"错误：必要文件{file}缺失")
            else:
                target_file = os.path.join(target_dir, file)
                shutil.copy2(file, target_file)
                print(f"已复制文件: {file} -> {target_file}")

        # 复制可选文件
        optional_files = ["README_zh.md", "README.OpenSource", "NOTICE", "TEST.md"]
        for file in optional_files:
            if os.path.isfile(file):
                target_file = os.path.join(target_dir, file)
                shutil.copy2(file, target_file)
                print(f"已复制可选文件: {file} -> {target_file}")

        print("必要文件复制完成")
    finally:
        os.chdir(original_dir)  # 返回原始目录

def _build_project():
    """构建项目"""
    # 获取当前目录名作为库名
    current_library = os.path.basename(os.getcwd())
    current_library_str = current_library
    
    # 定义模块名映射
    module_names = {
        "ohos_mqtt": "ohos_Mqtt",
        "ohos_coap": "libcoap",
        "ohos_ijkplayer": "ijkplayer",
        "ohos_videocompressor": "videoCompressor",
        "ohos_luaarkts": "luaarkts",
        "publish": "aki",
        "ohos_video_trimmer": "videotrimmer",
        "ohos-SwipeLayout": "SwipeLayout",
		"linphone_napi": "ohos_linphone",
        "ohos_jsonwebtoken": "jsonwebtoken"
    }
    
    # 检查是否存在 library 目录或 library_display_names 中定义的特殊情况
    if not os.path.exists(os.path.join(os.getcwd(), 'library')) and current_library_str not in module_names:
        print(f"当前库 '{current_library}' 既没有 library 目录，也没有特殊情况，跳过构建项目")
        return
    
    # 确定模块名
    module_name = "library"  # 默认模块名
    for lib_key, mod_name in module_names.items():
        if current_library_str == lib_key or current_library_str.endswith(f'_{lib_key}'):
            module_name = mod_name
            break

    # 并行构建参数
    build_args = ["--analyze=normal", "--parallel", "--incremental"]

    # 清理项目
    subprocess.run([
        node_path,
        hvigor_path,
        "-p", "product=default",
        "clean",
        *build_args,
        "--daemon"
    ], check=True)

    print(f"使用模块名: {module_name}")
    # 执行debug模式构建
    subprocess.run([
        node_path,
        hvigor_path,
        "--sync",
        "-p", "product=default",
        "-p", "buildMode=debug",
        *build_args,
        "--daemon"
    ], check=True)



    # 构建项目
    subprocess.run([node_path, hvigor_path,
                    "--mode", "module",
                    "-p", "product=default",
                    "-p", f"module={module_name}@default",
                    "assembleHar",
                    *build_args,
                    "--daemon",
                    ], check=True)

def _clone_repo(library_name):
    """处理带子模块的仓库克隆"""
    # 获取仓库信息
    owner, name, sub_dir = get_repo_info(library_name)
    if not owner or not name:
        print(f"错误：无法获取库 {library_name} 的仓库信息")
        return False

    # 需要递归克隆的仓库列表
    recurse_repos = {
        "openharmony_tpc_samples",
        "ohos_grpc_node", 
        "ohos_mqtt",
        "ohos_coap",
        "mp4parser",
        "CommonsCompress",
        "ohos_videocompressor",
        "jtar",
        "mars",
		"imageknifepro"
    }

    # 构建克隆URL
    base_url = f"https://gitcode.com/{owner}/{name}"
    clone_url = f"{base_url}.git"
    target_dir = name

    # 检查并更新已存在的目录
    if os.path.exists(target_dir):
        print(f"目录 {target_dir} 已存在，检查是否为Git仓库")
        try:
            os.chdir(target_dir)
            print(f"已切换到目录: {os.getcwd()}")
            # 确保目标目录是Git仓库
            if os.path.exists(".git"):
                print(f"目标目录 {target_dir} 是Git仓库，执行git pull更新")
                subprocess.run(["git", "reset",  "--hard"], check=True, capture_output=True, text=True)
                result = subprocess.run(["git", "pull"], check=True, capture_output=True, text=True)
                print(f"Git pull输出: {result.stdout}")
                print(f"成功更新仓库 {target_dir}")
            else:
                print(f"目标目录 {target_dir} 不是Git仓库，跳过git pull")
        except Exception as e:
            print(f"切换目录或执行git pull时出错: {str(e)}")
            return False
        finally:
            os.chdir("..")
            print(f"已返回上级目录: {os.getcwd()}")
    else:
        # 构建克隆命令
        cmd = ["git", "clone", clone_url]
        if name in recurse_repos:
            cmd.append("--recurse-submodules")
            print(f"克隆仓库 {clone_url} 及其子模块...")
        else:
            print(f"克隆仓库 {clone_url}...")

        # 执行克隆命令并捕获输出
        try:
            result = subprocess.run(cmd, check=True, capture_output=True, text=True)
            print(f"Git clone输出: {result.stdout}")
            if not os.path.exists(target_dir):
                print(f"错误：克隆命令执行成功，但目标目录 {target_dir} 不存在")
                return False
            print(f"成功克隆仓库到 {target_dir}")
            return True
        except subprocess.CalledProcessError as e:
            print(f"Git clone失败: {e}")
            print(f"错误输出: {e.stderr if hasattr(e, 'stderr') else '无错误输出'}")
            return False
        except Exception as e:
            print(f"克隆过程中发生未知错误: {str(e)}")
            return False